package shipwright;

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.joints.Point2PointJoint;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.debug.Arrow;
import com.jme3.texture.Texture;
import com.jme3.util.SkyFactory;
import jme3test.water.MyProjectedGrid;
import jme3test.water.ProjectedWaterProcessorWithRefraction;
import jme3test.water.WaterHeightGenerator;
import shipwright.controls.BoatControl;
import shipwright.parts.BoatBlock;
import shipwright.water.BuoyancyControl;

public class Main extends SimpleApplication {

    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }
    MyProjectedGrid grid;
    Geometry projectedGridGeometry;
    Geometry lightSphere;
    Node sceneNode;
    ProjectedWaterProcessorWithRefraction waterProcessor;

    @Override
    public void simpleInitApp() {
        cam.setFrustumPerspective(45.0f, (float) settings.getWidth() / (float) settings.getHeight(), 1f, 2000f);
        cam.setLocation(new Vector3f(0, 3, 20));

        cam.update();

        addSkybox();

        WaterHeightGenerator waterGenerator = new WaterHeightGenerator();
        grid = new MyProjectedGrid(timer, cam, 100, 70, 0.02f, waterGenerator);
        projectedGridGeometry = new Geometry("Projected Grid", grid);  // create cube geometry from the shape
        projectedGridGeometry.setCullHint(Spatial.CullHint.Never);
        projectedGridGeometry.setMaterial(setWaterProcessor());
        projectedGridGeometry.setLocalTranslation(0, 0, 0);
        rootNode.attachChild(projectedGridGeometry);


        /**
         * A white, directional light source
         */
        DirectionalLight sun = new DirectionalLight();
        sun.setDirection(new Vector3f(1, -1, -2).normalizeLocal());
        sun.setColor(ColorRGBA.White);
        rootNode.addLight(sun);

        AmbientLight al = new AmbientLight();
        al.setColor(ColorRGBA.White);
        rootNode.addLight(al);

        flyCam.setMoveSpeed(50f);
        //flyCam.setDragToRotate(true);
        //flyCam.setEnabled(false);

        BulletAppState bullet = new BulletAppState();
        stateManager.attach(bullet);

       // Node boat = BoatFactory.buildBoat(assetManager);
       // rootNode.attachChild(boat);
       // for(Spatial s : boat.getChildren()){
       //     bullet.getPhysicsSpace().add(s.getControl(RigidBodyControl.class));
       // }
        
        Node boat = new Node();
        Geometry block = BoatBlock.buildBoatBlock(assetManager);
        boat.attachChild(block);
        RigidBodyControl rbc = new RigidBodyControl(BoatBlock.mass);
        block.addControl(rbc);
        
        
  
        
        Geometry block2 = BoatBlock.buildBoatBlock(assetManager);
        boat.attachChild(block2);
        block2.setLocalTranslation(.5f,0,0);
        RigidBodyControl rbc2 = new RigidBodyControl(BoatBlock.mass);
        block2.addControl(rbc2);
        
        Point2PointJoint joint = new Point2PointJoint(rbc, rbc2, new Vector3f(.25f,0,0), new Vector3f(.25f,0,0));

        
        Geometry block3 = BoatBlock.buildBoatBlock(assetManager);
        boat.attachChild(block3);
        block3.setLocalTranslation(0,0,-.5f);
        RigidBodyControl rbc3 = new RigidBodyControl(BoatBlock.mass);
        block3.addControl(rbc3);
        
         Point2PointJoint joint2 = new Point2PointJoint(rbc, rbc3, new Vector3f(0,0,-.25f), new Vector3f(0,0,.25f));

        
        Geometry block4 = BoatBlock.buildBoatBlock(assetManager);
        boat.attachChild(block4);
        block4.setLocalTranslation(.5f,0,-.5f);
        RigidBodyControl rbc4 = new RigidBodyControl(BoatBlock.mass);
        block4.addControl(rbc4);
        
         Point2PointJoint joint3 = new Point2PointJoint(rbc3, rbc4, new Vector3f(.25f,0,0), new Vector3f(-.25f,0,0));
         Point2PointJoint joint4 = new Point2PointJoint(rbc2, rbc4, new Vector3f(0,0,-.25f), new Vector3f(0,0,.25f));

        
         rootNode.attachChild(boat);
         bullet.getPhysicsSpace().add(rbc);
          bullet.getPhysicsSpace().add(rbc2);
           bullet.getPhysicsSpace().add(rbc3);
            bullet.getPhysicsSpace().add(rbc4);
           bullet.getPhysicsSpace().add(joint);
            bullet.getPhysicsSpace().add(joint2);
             bullet.getPhysicsSpace().add(joint3);
              bullet.getPhysicsSpace().add(joint4);
         
        

        BuoyancyControl buoyancyControl = new BuoyancyControl(waterGenerator, timer, boat);
        bullet.getPhysicsSpace().addTickListener(buoyancyControl);
        
        // Geometry spatial = new Geometry("boat", new Box(3f,.5f,.5f));
        //Material mat = new Material(am, "Common/MatDefs/Light/Lighting.j3md");
       // Material mat = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
       // mat.setTexture("DiffuseMap", am.loadTexture("/Textures/wood_texture.jpg"));
       // spatial.setMaterial(mat);
       // spatial.setLocalTranslation(0, 0, 0);
       // rootNode.attachChild(spatial);

         BoatControl bc = new BoatControl(rbc3,rbc4, bullet, inputManager);
        attachCoordinateAxes(new Vector3f(0,0,0));

    }

    @Override
    public void simpleUpdate(float tpf) {
        float[] angles = new float[3];
        cam.getRotation().toAngles(angles);
        grid.update(cam.getViewMatrix().clone());

    }

    private void addSkybox() {

        String dir = "jme3test/water/data/skybox/";
        Texture north = assetManager.loadTexture(dir + "1.jpg");
        Texture south = assetManager.loadTexture(dir + "3.jpg");
        Texture east = assetManager.loadTexture(dir + "2.jpg");
        Texture west = assetManager.loadTexture(dir + "4.jpg");
        Texture up = assetManager.loadTexture(dir + "6.jpg");
        Texture down = assetManager.loadTexture(dir + "5.jpg");

        Spatial sky = SkyFactory.createSky(assetManager, west, east, north, south, up, down);

        sceneNode = new Node("Scene");
        sceneNode.attachChild(sky);
        rootNode.attachChild(sceneNode);
    }

    private Material setWaterProcessor() {

        waterProcessor = new ProjectedWaterProcessorWithRefraction(cam, assetManager);
        waterProcessor.setReflectionScene(sceneNode);
        waterProcessor.setDebug(false);
        viewPort.addProcessor(waterProcessor);
        return waterProcessor.getMaterial();
    }

    private void attachCoordinateAxes(Vector3f pos) {
        Arrow arrow = new Arrow(Vector3f.UNIT_X);
        arrow.setLineWidth(4); // make arrow thicker
        putShape(arrow, ColorRGBA.Red).setLocalTranslation(pos);

        arrow = new Arrow(Vector3f.UNIT_Y);
        arrow.setLineWidth(4); // make arrow thicker
        putShape(arrow, ColorRGBA.Green).setLocalTranslation(pos);

        arrow = new Arrow(Vector3f.UNIT_Z);
        arrow.setLineWidth(4); // make arrow thicker
        putShape(arrow, ColorRGBA.Blue).setLocalTranslation(pos);
    }

    private Geometry putShape(Mesh shape, ColorRGBA color) {
        Geometry g = new Geometry("coordinate axis", shape);
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.getAdditionalRenderState().setWireframe(true);
        mat.setColor("Color", color);
        g.setMaterial(mat);
        rootNode.attachChild(g);
        return g;
    }
}